package mz.co.research.server.mvc.services;

import java.util.Arrays;

import mz.co.framework.error.DaoException;
import mz.co.research.server.mvc.model.dao.jpa.RoleJpaDao;
import mz.co.research.server.mvc.model.dao.jpa.UserJpaDao;
import mz.co.research.shared.model.Role;
import mz.co.research.shared.model.User;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class SecurityUserService extends InMemoryDaoImpl implements
		UserDetailsService {

	@Autowired
	private UserJpaDao userJpaDao;

	@Autowired
	private RoleJpaDao roleJpaDao;

	@Override
	@Transactional(readOnly = true)
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {

		try {
			User user = userJpaDao.findByUsername(username);

			if (user == null) {
				throw new UsernameNotFoundException("User and Password invalid");
			}

			final Role role = roleJpaDao.findById(user.getRoleId());

			try {

				return super.loadUserByUsername(username);

			} catch (UsernameNotFoundException ue) {

				return new org.springframework.security.core.userdetails.User(
						user.getUsername(),
						user.getPassword(),
						user.getActive().booleanValue(),
						true,
						true,
						true,
						Arrays.asList(new GrantedAuthority[] { new GrantedAuthority() {
							@Override
							public String getAuthority() {
								return role.getCode();
							}
						} }));
			}
		} catch (DaoException de) {
			// FIXME : Apenas para compilar, porem deverá ser redesenhada essa
			// classe. O log NAO
			// pode ser engolido aqui.
			return null;
		}

	}
}
